//
// Created by root on 19-7-29.
//

#include <dlfcn.h>
#include "jni_utils.h"
#include "log_utils.h"

#define TAG "JNIUtils"

bool try_catch_impl(JNIEnv *env,bool output_stacktrace){
    if(env->ExceptionCheck()){
        if(output_stacktrace)
            env->ExceptionDescribe();
        env->ExceptionClear();
        return true;
    }
    return false;
}

bool TryCatch(JNIEnv *env) {
    return try_catch_impl(env,true);
}

bool TryCatch(JNIEnv *env, std::string customize_msg) {
    bool has_exception=try_catch_impl(env, false);
    if(has_exception)
        LOGE("%s\n",customize_msg.c_str());
    return has_exception;
}

JavaVM* get_java_vm() {
    static JavaVM *current_vm= nullptr;
    if (current_vm)
        return current_vm;
    static jint (*get_created_jvms)(JavaVM**, jsize, jsize*)= nullptr;

    if (!get_created_jvms) {
        get_created_jvms = reinterpret_cast<jint (*)(JavaVM **, jsize, jsize *)>
        (dlsym(RTLD_DEFAULT, "JNI_GetCreatedJavaVMs"));
        LOGD("get_created_jvms:%p\n", get_created_jvms);
        if (!get_created_jvms)
            return nullptr;
    }

    JavaVM *vms[10] = {nullptr};
    jint vm_count = 0;
    get_created_jvms(vms, 10, &vm_count);
    LOGD("created VMs count:%d\n", vm_count);
    if (vm_count <= 0)//There is no JVM created yet.
        return nullptr;
    current_vm = vms[0];//As for android,there will be only one JavaVM in all zygote's child process.
    return current_vm;
}

JNIEnv* get_jni_env(){
    JNIEnv* (*getJNIEnv)();
    void * android_runtime = dlopen("libandroid_runtime.so",RTLD_NOW);
    getJNIEnv =reinterpret_cast<JNIEnv *(*)()>(
            dlsym(android_runtime, "_ZN7android14AndroidRuntime9getJNIEnvEv")
            );
    if(!getJNIEnv){
        LOGE("fail to get getJNIEnv in libandroid_runtime.so\n");
        return nullptr;
    }
    return getJNIEnv();
}
